//
//  ClassExtension.swift
//  MeasureMould
//
//  Created by iOS on 2021/3/30.
//

import Foundation

extension String {

    /// String 使用下标截取字符串
    subscript(r:Range<Int>) -> String {
        get {
            let startIndex = self.index(self.startIndex, offsetBy: r.lowerBound)
            let endIndex = self.index(self.startIndex, offsetBy: r.upperBound)
            return String(self[startIndex ..< endIndex])
        }
    }


    /// 16进制字符串转Data
    func hexData() -> Data? {
        var data = Data(capacity: count/2)
        let regex = try! NSRegularExpression(pattern: "[0-9a-f]{1,2}", options: NSRegularExpression.Options.caseInsensitive)
        regex.enumerateMatches(in: self, options: .withTransparentBounds, range: NSMakeRange(0, utf16.count)) { (match, flags, stop) in
            let byteString = (self as NSString).substring(with: match!.range)
            var num = UInt8(byteString, radix: 16)!
            data.append(&num, count: 1)
        }
        guard data.count > 0 else {
            return nil
        }
        return data
    }

    func utf8Data() -> Data? {
        return self.data(using: .utf8)
    }

    // 将16进制字符串转化为 [UInt8]
    // 使用的时候直接初始化出 Data
    // Data(bytes: Array<UInt8>)
    func bytes(from hexStr: String) -> [UInt8] {
        //        print("hexStr:\(hexStr)")
        assert(hexStr.count % 2 == 0, "输入字符串格式不对，8位代表一个字符")
        var bytes = [UInt8]()
        var sum = 0
        // 整形的 utf8 编码范围
        let intRange = 48...57
        // 小写 a~f 的 utf8 的编码范围
        let lowercaseRange = 97...102
        // 大写 A~F 的 utf8 的编码范围
        let uppercasedRange = 65...70
        for (index, c) in hexStr.utf8CString.enumerated() {
            var intC = Int(c.byteSwapped)
            if intC == 0 {
                break
            } else if intRange.contains(intC) {
                intC -= 48
            } else if lowercaseRange.contains(intC) {
                intC -= 87
            } else if uppercasedRange.contains(intC) {
                intC -= 55
            } else {
                assertionFailure("输入字符串格式不对，每个字符都需要在0~9，a~f，A~F内")
            }
            sum = sum * 16 + intC
            // 每两个十六进制字母代表8位，即一个字节
            if index % 2 != 0 {
                bytes.append(UInt8(sum))
                sum = 0
            }
        }
        //    print(bytes)
        print(bytes.count)
        return bytes
    }


}

extension Data {
    ///Data转16进制字符串
    func hexString() -> String {
        return map {
            String(format: "%02x", $0)
        }.joined(separator: "").uppercased()
    }
}

extension Double {
    ///四舍五入 到小数点后某一位
    func roundTo(places: Int) -> Double {
        let divisor = pow(10.0, Double(places))
        return (self * divisor).rounded() / divisor
    }
    ///截断 到小数点后某一位
    func truncate(places: Int) -> Double {
        let divisor = pow(10.0, Double(places))
        return Double(Int(self * divisor)) / divisor
    }



}


/// 度转度分秒
/// - Parameter coordinate: 度
/// - Returns: 度分秒
func stringWithCoordinater(coordinate:String) -> String {
    let latNumber:Int = Int(Double(coordinate)!)
    let tp = (Double(coordinate)! - Double(latNumber)) * 60
    let fen = Int(tp)
    let miao = abs((tp - Double(fen)) * 60)
    let str:String = String(latNumber) + "°" + String(abs(fen)) + "'" + String(format: "%.4f", miao) + "\""
    return str

}


/// 度分秒转度
/// - Parameter dms: 度分秒
/// - Returns: 度
func changeToDu(dms:String) -> Double {
    guard dms.count > 0 else {
        return 0
    }

    let temp = dms.replacingOccurrences(of: " ", with: "")
    let str2 = temp.split(separator: "°")
    if str2.count < 2 {
        return 0
    }
    let d = Int(str2[0])
    let str3 = str2[1].split(separator: "′")
    if str3.count < 2 {
        return 0
    }
    let f = Int(str3.first!)
//    let index = str3[1].index(str3[1].endIndex, offsetBy: -1)
    let str4 = str3[1].prefix(str3[1].count-1)
    let m = Double(str4)
    let fen = Double(f!) + (m! / 60)
    let du = (fen / 60) + Double(abs(d!))
    return du

}


/// 海伦公式计算三角形面积
/// S = √p(p-a)(p-b)(p-c)
/// - Parameters:
///   - a: a边
///   - b: b边
///   - c: c边
/// - Returns: 面积
func hailunToArea(_ a:Double, b:Double, c:Double) -> Double {
    var s:Double = 0
    let pp:Double = (a + b + c) / 2.0
    let s1:Double = sqrt(fabs(pp))
    let s2:Double = sqrt(fabs(pp - a))
    let s3:Double = sqrt(fabs(pp - b))
    let s4:Double = sqrt(fabs(pp - c))
    s = s1 * s2 * s3 * s4
//    s = sqrt(fabs(pp * (pp - a) * (pp - b) * (pp - c)))
    return s
}

